#ifndef HGCORE_H
#define HGCORE_H

/*
 * Hosted Game Core
 * D1st0rt, SSCE Hyperspace
 * License: MIT/X11
 * Created: 2009-01-14
 * Updated: 2009-05-12
 *
 * Layer of abstraction that provides common functionality for games
 * having a human host. Games which desire use of the core should
 * implement the Ihostedgame interface and attach to both the arena and
 * this module. Only one Ihostedgame can be attached per arena.
 */

/* pyinclude: hosted/hgcore.h */

/** Structure for an individual team in a hosted game */
typedef struct HGTeam
{
    /* pytype: struct, struct HGTeam, hgteam */
    Arena *Arena;
    int Freq;
    int Status;
    void *Data;
}HGTeam;

/** Function to enumerate over all of the teams in an arena. */
typedef void (*HGTeamEnumFunc)(HGTeam *team, void *data);

/** Various status codes */
typedef enum HGStatus
{
    /* pyconst: enum, "HGS_*" */
    HGS_IDLE = 0,
    HGS_PREGAME,
    HGS_ACTIVE,
    HGS_PAUSED,
    HGS_POSTGAME,
    HGS_ELIMINATED, //for teams or players
}HGStatus;

/** Various reasons for things */
typedef enum HGReason
{
    /* pyconst: enum, "HGR_*" */
    HGR_FORCED = -4,
    // Normally you would end the game manually, HGR_FORCED is for
    // "Guess what, this is happening" like arena being destroyed

    HGR_CANCELLED = -3, //stopped in HGS_PREGAME
    HGR_STOPPED = -2, //stopped in HGS_ACTIVE
    HGR_NONE_REMAINING = -1,
    HGR_NATURAL = 0 //normal game ending, only 1 team left

    // Game-specific reasons will be passed through and should be > 1
}HGReason;

#define I_HOSTEDGAME "hostedgame"

/** Generic Hosted game module for use with HGCore.
 * This should be implemented by a game that wants to run off of the
 * HGCore interface.
 */
typedef struct Ihostedgame
{
    INTERFACE_HEAD_DECL
    /* pyint: use, impl */

    /** Will be called before the hgcore prepares the game.
     * @param arena the arena the game is in
     * @param host the player that is hosting the game
     * @param params the game setup arguments passed by the host
     * @return whether the game is ready for the hgcore to prepare
     */
    int (*OnPrepare)(Arena *a, Player *host, const char *params);
    /* pyint: arena, player, string -> int */

    /** Will be called before the hgcore starts the game.
     * @param arena the arena the game is in
     * @return whether the game is ready for the hgcore to prepare
     */
    int (*OnStart)(Arena *a, Player *host);
    /* pyint: arena, player -> int */

    /** Will be called after the hgcore ends the game.
     * @param arena the arena the game is in
     * @param how the way or reason the game ended (game-specific)
     */
    void (*OnGameOver)(Arena *a, int how);
    /* pyint: arena, int -> void */

    /** Will be called before the hgcore cleans up the game.
     * @param arena the arena the game is in
     */
    void (*OnCleanup)(Arena *a);
    /* pyint: arena -> void */

    /** Will be called after the hgcore creates a HGTeam.
     * @param arena the arena the game is in
     * @param team the team that was created
     */
    void (*OnTeamCreate)(Arena *a, HGTeam *team);
    /* pyint: arena, hgteam -> void */

    /** Will be called before the hgcore destroys a HGTeam.
     * @param arena the arena the game is in
     * @param team the team that is about to be destroyed
     */
    void (*OnTeamDestroy)(Arena *a, HGTeam *team);
    /* pyint: arena, hgteam -> void */

    /** Will be called when the Ihostedgame is attached in an arena.
     * This is so the hgcore knows how much memory to allocate for
     * each HGTeam in the HGTeam->Data pointer.
     * @return the size of the extra team data structure
     */
    int (*SizeOfTeamData)();
    /* pyint: -> int */

    /** Whatever this returns will be displayed after the team freq
     * and number of players in ?showteams.
     * @return a string of team info
     * @remarks this does not yet work in python modules
     */
    void (*TeamInfoString)(HGTeam *team, char *str, int buflen);
    /* pyint: hgteam, string inout, int buflen -> void */

}Ihostedgame;

#define DEF_HG_INT(name) local Ihostedgame hginterface = \
{ \
    INTERFACE_HEAD_INIT(I_HOSTEDGAME, name) \
 \
    OnPrepare, \
    OnStart, \
    OnGameover, \
    OnCleanup, \
    OnTeamCreate, \
    OnTeamDestroy, \
    SizeOfTeamData, \
    TeamInfoString \
}

#define I_HGCORE "hgcore"

/** Hosted Game core module for ASSS */
typedef struct Ihgcore
{
    INTERFACE_HEAD_DECL
    /* pyint: use */

    /** Attempts to set the Ihostedgame in a particular arena to a
     * specified module.
     * @param a the target arena
     * @param hgmod_name the name of the Ihostedgame module to attach
     * @return 1 if success, 0 if failure
     * @remarks will fail if there is already a game attached
     */
    int (*AttachGame)(Arena *a, const char *hgmod_name, const char *game_name);
    /* pyint: arena, string, string -> int */

    /** Attempts to disassociate the Ihostedgame module with the core
     * in a specified arena.
     * @param a the target arena
     * @return 1 if success, 0 if failure
     */
    int (*DetachGame)(Arena *a);
    /* pyint: arena -> int */

    /** Ends the currently running game.
     * @param a the target arena
     * @param how a status code for the way the game was ended
     * @see HGS_REASON
     */
    void (*EndGame)(Arena *a, int how);
    /* pyint: arena, int -> void */

    /** Adds a team to the game as "ineligible" which means it will
     * never be considered in the tally of remaining teams which
     * determines whether the game should end or not.
     * @param arena the arena to add the team in
     * @param freq the frequency the team is on
     */
    void (*AddIneligibleTeam)(Arena *a, int freq);
    /* pyint: arena, int -> void */

    /** Gets the hgcore game status of a player in a particular arena.
     * @param p the target player
     * @param a the desired arena to get status for
     * @return the status code of the player
     * @see HGS_STATUS
     */
    int (*PlayerStatus)(Player *p, Arena *a);
    /* pyint: player, arena -> int */

    /** Gets the hgcore game status of a team in a particular arena.
     * @param a the desired arena to get status for
     * @param freq the frequency of the team
     * @return the status code of the tean
     * @see HGS_STATUS
     */
    int (*TeamStatus)(Arena *a, int freq);
    /* pyint: arena, int -> int */

    /** Gets the hgcore game status of a particular arena.
     * @param a the target arena
     * @return the status code of the game
     * @see HGS_STATUS
     */
    int (*GameStatus)(Arena *a);
    /* pyint: arena -> int */

    /** Marks a player as eliminated in a particular game
     * @param a the arena to eliminate them in
     * @param p the player to eliminate
     */
    void (*EliminatePlayer)(Arena *a, Player *p);
    /* pyint: arena, player -> void */

    /** Marks a team as eliminated in a particular game
     * @param a the arena the team is in
     * @param freq the team's frequency
     * @remarks does not modify status of players on the team
     */
    void (*EliminateTeam)(Arena *a, int freq);
    /* pyint: arena, int -> void */

    /** Gets the number of remaining non-eliminated teams in an arena.
     * This is determined by any team whose status is not HGS_ELIMINATED
     * @param a the target arena
     * @return the number of teams left in the game, or -1 if no hosted game
     */
    int (*RemainingTeams)(Arena *a);
    /* pyint: arena -> int */

    /** Helper function for python modules since Ipersist's
     * EndInterval is not available
     * @param a the target arena
     * @param interval an interval_t from statcodes.h
     */
    void (*EndInterval)(Arena *a, int interval);
    /* pyint:  arena, int -> void */

    /** Calls func on all of the HGTeams in a particular arena
     * @param a the target arena
     * @param func a HGTeamEnumFunc to call on each HGTeam
     * @param data optional data to pass to func
     * @see HGTeamEnumFunc
     */
    void (*TeamEnum)(Arena *a, HGTeamEnumFunc *func, void *data);

    /** This is used to retrieve the information in HGTeam->Data
     * @param a the arena the team is in
     * @param freq the frequency of the team
     * @return a pointer to the team's extra data
     */
    void *(*GetTeamData)(Arena *a, int freq);
}Ihgcore;

#endif
